package at.kokoni.Koko_Ni;

import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.util.Base64;
import android.util.Base64InputStream;
import android.util.Log;
import android.view.View;
import android.widget.*;
import com.androidmapsextensions.Marker;
import com.androidmapsextensions.MarkerOptions;
import at.kokoni.Koko_Ni.entities.Image;
import at.kokoni.Koko_Ni.entities.Post;
import at.kokoni.Koko_Ni.util.GPSTracker;
import at.kokoni.Koko_Ni.util.ImageUtil;
import at.kokoni.Koko_Ni.util.PostUtil;
import com.androidmapsextensions.*;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.codec.binary.Base64OutputStream;

import java.io.*;

public class MapActivity extends FragmentActivity
		implements GoogleMap.OnCameraChangeListener,
		GoogleMap.OnMapLongClickListener,
		GoogleMap.OnMarkerClickListener,
		GoogleMap.OnInfoWindowClickListener,
		GoogleMap.OnMyLocationButtonClickListener {
	private GoogleMap googleMap;
	private String session;
	private GPSTracker tracker;
	private static final int CAMERA_PIC_REQUEST = 1313;
	private Uri imageUri;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.maplayout);
		session = this.getIntent().getStringExtra("session");
		tracker = new GPSTracker(this);
		setupMap();
	}

	@Override
	protected void onStart() {
		super.onStart();
	}

	@Override
	protected void onPause() {
		super.onPause();
		tracker.stopUsingGPS();
	}

	@Override
	protected void onStop() {
		super.onStop();
		tracker.stopUsingGPS();
	}

	@Override
	protected void onResume() {
		super.onResume();
		setupMap();
	}

	private void setupMap() {
		if (googleMap == null) {
			FragmentManager fragmentManager = getSupportFragmentManager();
			Fragment fragment = fragmentManager.findFragmentById(R.id.mapFragment);
			googleMap = ((SupportMapFragment) fragment).getExtendedMap();
			if (googleMap != null) {
				googleMap.setOnCameraChangeListener(this);
				googleMap.setOnMapLongClickListener(this);
				googleMap.setOnMarkerClickListener(this);
				googleMap.setOnInfoWindowClickListener(this);
				googleMap.setOnMyLocationButtonClickListener(this);
				googleMap.setMyLocationEnabled(true);
				Location location = tracker.getLocation();
				if (location != null) {
					//Location location = tracker.getLocation();
					googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 14));
				} else {
					new AlertDialog.Builder(this).setMessage("Cannot find current location").setNeutralButton(":(", null).create().show();
				}
				loadPosts(googleMap.getProjection().getVisibleRegion().latLngBounds);
			}
		}
	}

	@Override
	public void onCameraChange(final CameraPosition position) {
		loadPosts(googleMap.getProjection().getVisibleRegion().latLngBounds);
	}

	@Override
	public void onMapLongClick(final LatLng latLng) {
		createPost();
	}

	private void createPost() {
		AlertDialog.Builder alert = new AlertDialog.Builder(this);
		alert.setTitle("create post");
		Location location = null;
		if (tracker.canGetLocation()) {
			location = tracker.getLocation();
		} else {
			new AlertDialog.Builder(this).setMessage("Cannot find current location").setNeutralButton(":(", null).create().show();
			return;
		}
		final LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
		final View layout = this.getLayoutInflater().inflate(R.layout.createpostlayout, null);
		alert.setView(layout);

		alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {

				EditText editText = ((EditText) layout.findViewById(R.id.createPostEditText));
				Editable editable = editText.getText();
				String text = editable.toString();
				java.io.ByteArrayOutputStream stream = new java.io.ByteArrayOutputStream();
				String base64 = null;
				try {
					encode(new File(imageUri.getPath()), stream);
					base64 = stream.toString("UTF-8");
					stream.close();
				} catch (Exception e) {

				}
				new PostUtil() {
					@Override
					protected void onPostExecute(Post[] posts) {
						super.onPostExecute(posts);
						loadPosts(googleMap.getProjection().getVisibleRegion().latLngBounds);
					}
				}.execute("post.create", text, latLng, session, base64);
			}
		});

		alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {

			}
		});
		alert.show();
	}

	private void encode(File file, OutputStream base64OutputStream) throws IOException {
		InputStream is = new FileInputStream(file);
		OutputStream out = new android.util.Base64OutputStream(base64OutputStream, Base64.NO_WRAP);
		IOUtils.copy(is, out);
		is.close();
		out.close();
	}

	private void decode(File file, InputStream base64InputStream) throws IOException {
		OutputStream out = new FileOutputStream(file);
		InputStream in = new Base64InputStream(base64InputStream, Base64.NO_WRAP);
		IOUtils.copy(in, out);
		in.close();
		out.close();
	}

	private void loadPosts(LatLngBounds latLngBounds) {
		ProgressBar bar = ((ProgressBar) findViewById(R.id.postloadingbar));
		if (googleMap.getCameraPosition().zoom < 10) {
			bar.setVisibility(View.INVISIBLE);
			googleMap.clear();
			return;
		}

		bar.setVisibility(View.VISIBLE);
		try {
			new PostUtil() {
				@Override
				protected void onPostExecute(Post[] posts) {
					super.onPostExecute(posts);
					ProgressBar bar = ((ProgressBar) findViewById(R.id.postloadingbar));
					Button button = ((Button) findViewById(R.id.connectionStateButton));
					if (posts == null) {
						bar.setVisibility(View.INVISIBLE);
						button.setVisibility(View.VISIBLE);
						return;
					}
					googleMap.clear();
					for (Post p : posts) {
						googleMap.addMarker(new MarkerOptions().position(new LatLng(p.getLatitude(), p.getLongitude())).title(p.getText()).snippet(p.getUserName()).data(p));
					}

					bar.setVisibility(View.INVISIBLE);
					button.setVisibility(View.INVISIBLE);

				}
			}.execute("post.coordinates", latLngBounds);

		} catch (Exception ex) {
		}
	}

	@Override
	public boolean onMarkerClick(Marker marker) {
		marker.showInfoWindow();
		return true;
	}

	@Override
	public void onInfoWindowClick(Marker marker) {
		final View layout = this.getLayoutInflater().inflate(R.layout.postoverviewlayout, null);
		Post p = marker.getData();
		if (p.getImages() != null) {
			final ProgressBar loadingBar = (ProgressBar) layout.findViewById(R.id.imageLoadingProgressBar);
			loadingBar.setVisibility(View.VISIBLE);
			new ImageUtil() {
				@Override
				protected void onPostExecute(Image image) {
					super.onPostExecute(image);
					loadingBar.setVisibility(View.GONE);
					/*ImageView imageView = (ImageView) layout.findViewById(R.id.imageView);
					byte[] imageAsBytes = Base64.decode(image.getBase64Data(), Base64.DEFAULT);
					Bitmap bitmap = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
					imageView.setImageBitmap(bitmap);*/
					File photo = null;

					try {
						ByteArrayInputStream inputStream = new ByteArrayInputStream(image.getBase64Data().getBytes("UTF-8"));
						photo = createTemporaryFile("picture", ".jpg");
						photo.delete();
						decode(photo, inputStream);
						inputStream.close();
						imageUri = Uri.parse(photo.toURI().toString());
					} catch (Exception e) {
						Log.e("Photo", "Can't create file to take picture!");
						return;
					}
					ImageView imageView = (ImageView) layout.findViewById(R.id.imageView);
					imageView.setImageURI(imageUri);
				}
			}.execute("image.id", p.getImages()[0]);
		}
		AlertDialog.Builder alert = new AlertDialog.Builder(this);
		((TextView) layout.findViewById(R.id.textView)).setText(marker.getTitle());
		alert.setView(layout);
		alert.setTitle(marker.getSnippet());
		alert.setNeutralButton("Ok", null);
		alert.create().show();
	}

	private File createTemporaryFile(String part, String ext) throws Exception {
		File tempDir = Environment.getExternalStorageDirectory();
		tempDir = new File(tempDir.getAbsolutePath() + "/.temp/");
		if (!tempDir.exists()) {
			tempDir.mkdir();
		}
		return File.createTempFile(part, ext, tempDir);
	}

	public void onImageClicked(View view) {
		ImageView imageView = (ImageView) findViewById(R.id.imageView);

		Intent intent = new Intent();
		intent.setAction(Intent.ACTION_VIEW);
		intent.setDataAndType(imageUri, "image/png");
		startActivity(intent);
	}

	public void onAddPhotoButtonClicked(View view) {
		Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		File photo;
		try {
			photo = this.createTemporaryFile("picture", ".jpg");
			photo.delete();
		} catch (Exception e) {
			Log.e("Photo", "Can't create file to take picture!");
			return;
		}
		imageUri = Uri.fromFile(photo);
		cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
		startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
	}

	public void onPostCreateButtonClick(View view) {
		createPost();
	}

	public void onConnectionStateButtonClicked(View view) {
		new AlertDialog.Builder(this).setMessage("No internet connection or Asoko is offline. Please check back later.").setNeutralButton(":(", null).create().show();
	}

	@Override
	public boolean onMyLocationButtonClick() {
		Location location = tracker.getLocation();
		if (location != null) {

			googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 14));
		} else {
			new AlertDialog.Builder(this).setMessage("Cannot find current location").setNeutralButton(":(", null).create().show();
		}
		return true;
	}
}
